package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.config.AilPayConfig;
import cn.itsource.ymcc.constant.ConstantsOrder;
import cn.itsource.ymcc.constant.PayConstants;
import cn.itsource.ymcc.domain.PayFlow;
import cn.itsource.ymcc.domain.PayOrder;
import cn.itsource.ymcc.dto.PaySuccessDto;
import cn.itsource.ymcc.exception.GlobalException;
import cn.itsource.ymcc.mapper.PayFlowMapper;
import cn.itsource.ymcc.mapper.PayOrderMapper;
import cn.itsource.ymcc.service.IPayOrderService;
import cn.itsource.ymcc.vo.ApplyVo;
import cn.itsource.ymcc.vo.PayOrderVo;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.common.models.AlipayTradeCloseResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zongchangjiang
 * @since 2023-04-11
 */
@Service
@Slf4j
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {
    @Autowired
    private AilPayConfig ailPayConfig;
    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public void save(PayOrderVo payOrderVo) {
        PayOrder payOrder = new PayOrder();
        BeanUtils.copyProperties(payOrderVo,payOrder);
        baseMapper.insert(payOrder);
    }

    @Override
    public String apply(ApplyVo applyVo) {
        //判断支付类型    2.switch    3.策略模式4.状态码模块(拓展) 设计模式配合业务  不是哪里都适合
        //1.if  一个一个往下面判断
        //2.switch
        Integer payType = applyVo.getPayType();
        String result = "";
        switch (payType){
            case ConstantsOrder.ORDER_PAY_0:
                result = yuE(applyVo);
                break;
            case ConstantsOrder.ORDER_PAY_1:
                result = zhiFuBao(applyVo);
                break;
            case ConstantsOrder.ORDER_PAY_2:
                result = weiXin(applyVo);
                break;
            default:
               //3银联
        }
        return result;
    }

    /**
     * 修改支付单 这TM要些什么数据
     * 添加流水   这TM要些什么数据
     *  使用openfeign远程调用 强一致性(同时成功)
     *  使用mq 异步 (最终一致性) 简单多了
     * 修改订单
     * 修改课程销量 支付状态 添加一条购买记录
     */
    @Transactional
    @Override
    public void paySuccess(Map<String,String> parameter) {
        //修改支付单
        String orderNo = parameter.get("out_trade_no");
        //当前使用的订单号
        PayOrder payOrder = baseMapper.selectOne(new QueryWrapper<PayOrder>().eq("order_no", orderNo));
        payOrder.setUpdateTime(new Date());
        payOrder.setPayStatus(ConstantsOrder.ORDER_STATUS_1);
        baseMapper.updateById(payOrder);
        //添加流水
        PayFlow payFlow = new PayFlow();

//        交易时间
        String s = parameter.get("notify_time");
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(s);
            payFlow.setNotifyTime(parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }

//        标题
        payFlow.setSubject(payOrder.getSubject());
//        交易号，对应订单号
        payFlow.setOutTradeNo(payOrder.getOrderNo());
//        金额
        payFlow.setTotalAmount(payOrder.getAmount());
//        交易状态
        payFlow.setTradeStatus(parameter.get("trade_status"));
//        错误码
//        错误信息
//        回传参数
        payFlow.setPassbackParams(parameter.get("passback_params"));
        payFlow.setPaySuccess(true);
        payFlow.setResultDesc("支付成功");
        payFlowMapper.insert(payFlow);


        //分析 我需要传什么参数到  order服务和 course服务
        /*
        - 订单服务中需要修改订单状态，也就只需要订单编号即可
          订单编号  和 订单状态
        - 课程服务中需要添加用户购买课程记录（t_course_user_learn）需要用户id、课程id和订单编号，统计消息+1需要课程id和购买的数量
          课程id  和 用户id
         */
        //定义生产者 发送同步消息

        PaySuccessDto paySuccessDto = new PaySuccessDto();
        paySuccessDto.setOrderNo(orderNo);
        paySuccessDto.setUserId(payOrder.getUserId());
        //设置课程id   ?courseIds=7,8,9&aaa=bbb&AAA=ccc
        String extParams = payOrder.getExtParams();
        paySuccessDto.setCourseId(getCourseId(extParams));
        paySuccessDto.setOrderStatus(ConstantsOrder.ORDER_STATUS_1);
        //发送一个同步消息
        rocketMQTemplate.syncSend(PayConstants.TOPIC_PAY_RESULT+":"+PayConstants.TAGS_PAY_RESULT,
                MessageBuilder.withPayload(JSON.toJSONString(paySuccessDto)).build()
                );
    }

    @Override
    public void payOutTime(String orderNo) {
        //只是修改状态
        PayOrder payOrder = baseMapper.selectOne(new QueryWrapper<PayOrder>().eq("order_no", orderNo));
        if(payOrder.getPayStatus() == ConstantsOrder.ORDER_STATUS_0){
            payOrder.setPayStatus(ConstantsOrder.ORDER_STATUS_4);
            baseMapper.updateById(payOrder);
        }
        //调用支付宝去关单
        try {
            Config options = ailPayConfig.getOptions();
            Factory.setOptions(options);
            AlipayTradeCloseResponse close = Factory.Payment.Common().close(orderNo);
            if(close.getCode().equals("10000")){
                log.info("支付宝关单成功");
            }else {
                log.info("支付宝关单失败");
            }
        } catch (Exception e) {
            log.error("支付申请异常 {}",e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 格式 extParams
     * @param extParams
     * @return 课程ids
     */
    public List<Long> getCourseId(String extParams){
        List<Long> result = new ArrayList<>();
        //courseIds=7,8,9&aaa=bbb&AAA=ccc
        String substring = extParams.substring(1);
        //courseIds=7,8,9
        //aaa=bbb
        //AAA=ccc
        String[] split = substring.split("&");
        for (String s : split) {
            //courseIds
            //7,8,9
            String[] split1 = s.split("=");
            for (int i = 0; i < split1.length; i++) {
                if(split1[0].equalsIgnoreCase("courseIds")){
                    //7
                    //8
                    //9
                    String[] split2 = split1[1].split(",");
                    for (String s1 : split2) {
                        result.add(Long.valueOf(s1));
                    }
                    break;
                }
            }
        }
        return result;
    }


    /**
     * 支付宝支付
     * @param applyVo
     */
    private String zhiFuBao(ApplyVo applyVo) {
        //查询数据库
        PayOrder payOrder = baseMapper.selectOne(new QueryWrapper<PayOrder>().eq("order_no", applyVo.getOrderNo()));
        Config options = ailPayConfig.getOptions();
        //"http://6bwdbt.natappfree.cc/ymcc/pay/payOrder/asyncNotify"
        //options.notifyUrl = options.notifyUrl+payOrder.getExtParams();  //验证就会成功二次验签
        Factory.setOptions(options);
        try {
            //String subject  普通订单  标题
            //String outTradeNo   订单编号
            //String totalAmount   金额
            //String returnUrl     回调地址
            AlipayTradePagePayResponse response = Factory.Payment.Page()
                    .pay(payOrder.getSubject(), applyVo.getOrderNo(),
                            payOrder.getAmount().toString(), applyVo.getCallUrl());
            // 3. 处理响应或异常
            if (ResponseChecker.success(response)) {
                return response.getBody();
            } else {
                throw new GlobalException("支付宝接口调用失败:"+response.getBody());
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new GlobalException(e.getMessage());
        }
    }


    /**
     * 微信支付
     * @param applyVo
     */
    private String weiXin(ApplyVo applyVo) {
        return "";
    }

    /**
     * 余额支付
     * @param applyVo
     */
    private String yuE(ApplyVo applyVo) {
        return "";
    }


}
